summaryrefslogtreecommitdiff
path: root/app/api/auth/[...nextauth]/route.ts
diff options
context:
space:
mode:
Diffstat (limited to 'app/api/auth/[...nextauth]/route.ts')
-rw-r--r--app/api/auth/[...nextauth]/route.ts89
1 files changed, 62 insertions, 27 deletions
diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts
index 68cc3a5b..fe93906d 100644
--- a/app/api/auth/[...nextauth]/route.ts
+++ b/app/api/auth/[...nextauth]/route.ts
@@ -89,9 +89,9 @@ let securitySettingsCache: {
async function getCachedSecuritySettings() {
const now = Date.now()
-
- if (!securitySettingsCache.data ||
- (now - securitySettingsCache.lastFetch) > securitySettingsCache.ttl) {
+
+ if (!securitySettingsCache.data ||
+ (now - securitySettingsCache.lastFetch) > securitySettingsCache.ttl) {
try {
securitySettingsCache.data = await getSecuritySettings()
securitySettingsCache.lastFetch = now
@@ -102,7 +102,7 @@ async function getCachedSecuritySettings() {
}
}
}
-
+
return securitySettingsCache.data
}
@@ -110,15 +110,15 @@ async function getCachedSecuritySettings() {
function getClientIP(req: any): string {
const forwarded = req.headers['x-forwarded-for']
const realIP = req.headers['x-real-ip']
-
+
if (forwarded) {
return forwarded.split(',')[0].trim()
}
-
+
if (realIP) {
return realIP
}
-
+
return req.ip || req.connection?.remoteAddress || '127.0.0.1'
}
@@ -212,7 +212,7 @@ export const authOptions: NextAuthOptions = {
// DB에 로그인 세션 생성
const ipAddress = getClientIP(req)
const userAgent = req.headers?.['user-agent']
-
+
const dbSession = await SessionRepository.createLoginSession({
userId: user.id,
ipAddress,
@@ -243,7 +243,7 @@ export const authOptions: NextAuthOptions = {
}
},
}),
-
+
// 1차 인증용 프로바이더 (기존 유지)
CredentialsProvider({
id: 'credentials-first-auth',
@@ -283,6 +283,7 @@ export const authOptions: NextAuthOptions = {
callbacks: {
// ✅ JWT callback에 roles 정보 추가
+ // JWT callback 수정
async jwt({ token, user, account, trigger, session }) {
const securitySettings = await getCachedSecuritySettings()
const sessionTimeoutMs = securitySettings.sessionTimeoutMinutes * 60 * 1000
@@ -301,19 +302,50 @@ export const authOptions: NextAuthOptions = {
token.authMethod = user.authMethod
token.sessionExpiredAt = reAuthTime + sessionTimeoutMs
token.dbSessionId = user.dbSessionId
- token.roles = user.roles // ✅ roles 정보 추가
+ token.roles = user.roles
+ }
+
+ // ✅ 기존 토큰이 있고 로그인이 아닌 경우, DB에서 최신 사용자 정보 조회
+ if (token.id && !user && trigger !== "update") {
+ try {
+ const latestUser = await getUserById(parseInt(token.id))
+
+ if (latestUser) {
+ // 도메인이 변경되었다면 토큰 업데이트
+ if (token.domain !== latestUser.domain) {
+ console.log(`Domain changed for user ${token.email}: ${token.domain} -> ${latestUser.domain}`)
+ token.domain = latestUser.domain
+ }
+
+ // 기타 정보도 최신 상태로 업데이트
+ token.name = latestUser.name
+ token.companyId = latestUser.companyId
+ token.techCompanyId = latestUser.techCompanyId
+
+ // roles 정보도 최신으로 업데이트
+ const userRoles = await getUserRoles(parseInt(token.id))
+ token.roles = userRoles
+ }
+ } catch (error) {
+ console.error('Failed to fetch latest user info in JWT callback:', error)
+ }
}
// SAML 인증 시 DB 세션 생성 및 roles 조회
if (account && account.provider === 'credentials-saml' && token.id) {
const reAuthTime = Date.now()
const sessionExpiredAt = new Date(reAuthTime + sessionTimeoutMs)
-
+
try {
const numericUserId = ensureNumber(token.id)
-
- // ✅ SAML 로그인 시에도 roles 정보 조회
- if (!token.roles) {
+
+ // SAML 로그인 시에도 최신 사용자 정보 조회
+ const latestUser = await getUserById(numericUserId)
+ if (latestUser) {
+ token.domain = latestUser.domain
+ token.name = latestUser.name
+ token.companyId = latestUser.companyId
+ token.techCompanyId = latestUser.techCompanyId
token.roles = await getUserRoles(numericUserId)
}
@@ -323,7 +355,7 @@ export const authOptions: NextAuthOptions = {
authMethod: 'saml',
sessionExpiredAt,
})
-
+
token.authMethod = 'saml'
token.reAuthTime = reAuthTime
token.sessionExpiredAt = reAuthTime + sessionTimeoutMs
@@ -338,7 +370,7 @@ export const authOptions: NextAuthOptions = {
if (session.reAuthTime !== undefined) {
token.reAuthTime = session.reAuthTime
token.sessionExpiredAt = session.reAuthTime + sessionTimeoutMs
-
+
// DB 세션 업데이트
if (token.dbSessionId) {
await SessionRepository.updateLoginSession(token.dbSessionId, {
@@ -347,28 +379,31 @@ export const authOptions: NextAuthOptions = {
})
}
}
-
+
if (session.user) {
if (session.user.name !== undefined) token.name = session.user.name
if (session.user.email !== undefined) token.email = session.user.email
if (session.user.image !== undefined) token.imageUrl = session.user.image
+
+ // ✅ 세션 업데이트 시 도메인 정보도 갱신 가능
+ if (session.user.domain !== undefined) token.domain = session.user.domain
}
}
return token
- },
-
+ }
+,
// ✅ Session callback에 roles 정보 추가
async session({ session, token }: { session: Session; token: JWT }) {
// 세션 만료 체크
if (token.sessionExpiredAt && Date.now() > token.sessionExpiredAt) {
console.log(`Session expired for user ${token.email}. Expired at: ${new Date(token.sessionExpiredAt)}`)
-
+
// DB 세션 만료 처리
if (token.dbSessionId) {
await SessionRepository.logoutSession(token.dbSessionId)
}
-
+
return {
expires: new Date(0).toISOString(),
user: null as any
@@ -414,17 +449,17 @@ export const authOptions: NextAuthOptions = {
async signIn({ user, account, profile }) {
const securitySettings = await getCachedSecuritySettings()
console.log(`User ${user.email} signed in via ${account?.provider} (authMethod: ${user.authMethod}), session timeout: ${securitySettings.sessionTimeoutMinutes} minutes`);
-
+
// 이미 MFA에서 DB 세션이 생성된 경우가 아니라면 여기서 생성
if (account?.provider !== 'credentials-mfa' && user.id) {
try {
const numericUserId = ensureNumber(user.id)
-
+
// 기존 활성 세션 확인
const existingSession = await SessionRepository.getActiveSessionByUserId(numericUserId)
if (!existingSession) {
const sessionExpiredAt = new Date(Date.now() + (securitySettings.sessionTimeoutMinutes * 60 * 1000))
-
+
await SessionRepository.createLoginSession({
userId: numericUserId,
ipAddress: '0.0.0.0',
@@ -437,14 +472,14 @@ export const authOptions: NextAuthOptions = {
}
}
},
-
+
async signOut({ session, token }) {
console.log(`User ${session?.user?.email || token?.email} signed out`);
-
+
// DB에서 세션 로그아웃 처리
const userId = session?.user?.id || token?.id
const dbSessionId = session?.user?.dbSessionId || token?.dbSessionId
-
+
if (dbSessionId) {
await SessionRepository.logoutSession(dbSessionId)
} else if (userId) {